/* 2025.05
 *
 * IocHub Lib for Windwos/ Linux    
 *
 * Copyright (C) 2025 Nanjing Qinheng Microelectronics Co., Ltd.
 * Web:      http://wch.cn
 * Author:   WCH <tech@wch.cn>
 * Version:  V1.2
 *
 */
#ifndef IOCHUB_H_
#define IOCHUB_H_

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

#define DEFAULT_IOCHUB_START_TIMEOUT            5000    // 单位：ms
#define DEFAULT_IOCHUB_OPEN_SESSION_TIMEOUT     5000    // 单位：ms    
#define DEFAULT_ID_LENGTH   8
#define EVENT_RELAY_START              0x01        // 启动服务               对应：service_event_t
#define EVENT_RELAY_STOP               0x02        // 停止服务               对应：service_event_t
//todo: 2025.02.28新增
#define EVENT_EXCEPT_RELAY_STOP        0x03        // 网络异常停止服务        对应：service_event_t 
#define EVENT_NETWORK_BUSY             0x04        // 网络不稳定             对应：service_event_t 
#define EVENT_ACTIVE_SESSION_OPEN      0x05        // 主动打开会话            对应：session_event_t
#define EVENT_UNACTIVE_SESSION_OPEN    0x06        // 被动打开会话            对应：session_event_t
#define EVENT_SESSION_READ_NOTIFY      0x07        // 会话读通知              对应：session_read_event_t
#define EVENT_SESSION_CTRL_READ_NOTIFY       0x0B  // 会话控制读通知           对应：session_read_event_t
#define EVENT_SESSION_CLOSE            0x08        // 会话关闭                对应：session_event_t
#define EVENT_SESSION_TRANSFER_TYPE_CHANGE   0x09  // 会话通信模式变化         对应：session_transfer_change_event_t
#define EVENT_SESSION_EXCEPTION        0x0A        // 会话异常                对应：session_exception_event_t
#define EVENT_OPERATION_ERR            0x0F        // 错误异常                对应：service_event_t


/**
 * 局域网扫描结果
 */
typedef struct IOCHUB_LAN_SCAN_RESULT_S {
    unsigned char addrStr[64];   // IP地址字符串 IPV4  16字节，IPV6：64字节
    char nodeID[16];
} LAN_SCAN_RESULT_T;

/**
 * 会话打开、关闭事件回调值
*/
typedef struct IOCHUB_SESSION_EVENT_S {
    int sessionFd;                                // 会话标识
    char peerNodeIdStr[2 * DEFAULT_ID_LENGTH];    // 对端ID的字符串
    char mode;                                    // 主动or被动，0：主动  1：被动
    int errCo;                                    // 处理结果, 0x00:成功  其他:错误码
} session_event_t, SESSION_EVENT_T;

typedef struct IOCHUB_LOCAL_NET_ADDR_S {
	unsigned char ipAddrStr[16];    // IP地址字符串 IPV4  16字节 如：192.168.1.2
	unsigned char maskAddrStr[16];  // 子网掩码 如：255.255.255.0
} local_net_addr_t;

typedef struct IOCHUB_CONNECTED_SESSION_PEER_ADDR {
	unsigned char selfNodeAddrStr[64];            // 本地地址
	unsigned short selfPort;							      // 本机端口号
	unsigned char oppositeNodeAddrStr[64];	      // 对端地址
	unsigned short oppositePort;				              // 对端端口号
} connected_session_addr;


/**
 * 会话过程中接收到数据通知应用read结构体
*/
typedef struct IOCHUB_SESSION_READ_EVENT_S {
    int sessionFd;                                // 读会话标识
    int min_readable_len;                         // 最小可读长度
} session_read_event_t, SESSION_READ_EVENT_T;

/**
 * 会话过程中传输通道切换通知结构体
*/
typedef struct IOCHUB_SESSION_TRANSFER_CHANGE_EVENT_S {
    int sessionFd;                                // 会话标识
    int type;                                     // 模式
} session_transfer_change_event_t, SESSION_TRANSFER_CHANGE_EVENT_T;

/**
 * 会话过程中异常通知结构体
*/
typedef struct IOCHUB_SESSION_EXCEPTION_EVENT_S {
    int sessionFd;                                // 会话标识
    int errCo;                                    // 处理结果, 0x00:成功  其他:错误码
} session_exception_event_t, SESSION_EXCEPTION_EVENT_T;

/**
 * 服务异常值
*/
typedef struct IOCHUB_SERVICE_ERR_EVENT_S {
    int errCo;                                    // 处理结果, 0x00:成功  其他:错误码
} service_event_t, SERVICE_EVENT_T;

/**
 *  初始化参数
 */
typedef struct IOCHUB_INIT_CFG_S {
	// 接收缓冲区大小，不小于32KB，默认1024 * 1024（字节）
	unsigned int recvBufferSize;
	// 发送缓冲区大小，不小于32KB，默认1024 * 1024（字节）
	unsigned int sendBufferSize;
	// 控制传输缓冲区大小 不大于1MB字节，默认512 * 1024（字节）
	unsigned int ctrlDataBufferSize;
	// 最大连接数量，默认10
	unsigned int maxConnSize;
	// 每包发送数据大小，不大于10KB，默认4 * 1024（字节）
	unsigned int sendSizePerPackage;
	// 窗口大小
	unsigned int socketWndSize;
    // 窗口定时应答时间，默认200（毫秒）
	unsigned int socketWndTimeout;
	// 是否开启TLS，默认false（保留，暂不开放）
	bool supportTLS;
	// 是否开启DTLS，默认false（保留，暂不开放）
	bool supportDTLS;
	// 是否开启数据压缩传输，默认false
	bool supportCompress;
	// 是否开启设备锁，默认false
	bool openDeviceLock;
	// 节点属性，0x00：节点终端  0x01：通用网关	0x02：专用接口网关
	unsigned int peerProperty;	
    // 本地网卡，格式如："192.168.111.93,192.168.1.100"，以英文逗号隔开
    unsigned char localNetwork[128];			
} init_cfg_t, IOCHUB_INIT_CFG_T;

typedef struct IOCHUB_SESSION_ACCESS_MODE_S {
	/**
	 * 0：公开访问，只需要DevID即可建立会话连接；
     * 1：受限访问，需要DevID及会话密钥建立会话连接；
     * 2：私有，不接受建立会话连接请求；
	*/
	int modeType;    
    /** 会话秘钥 */ 
	char *sessionKey;
    /** 会话密钥字符串长度 */
	int keySize;
} access_mode_t, IOCHUB_ACCESS_MODE_T;

/**
 * 局域网回调函数声明
*/
typedef void (*lan_scan_cb)(LAN_SCAN_RESULT_T * pLanDevNodes, int nodeSize);
/**
 * 事件回调函数声明
*/
typedef void (*iochub_event_cb)(int eventCode, void * eventData);
/**
 *  描述：初始化库，在使用IoCHub通信前必须先调用该函数
 *  阻塞方式：非阻塞，立即返回
 *  appSign [IN]软件应用标识，可为空，若不为空时，长度不能超50字符，可用于单机多应用场景
 *  返回值： 0：操作成功 
 *        705：初始化IoCHub库失败
 */
int IoCHub_Init(char * appSign);

/**
 *  描述：注册IoCHub事件，启动/关闭服务、打开/关闭会话、会话读数据等通过该接口回调应用端
 *  阻塞方式：非阻塞，无返回值
*/
void IoCHub_RegisterEvent(iochub_event_cb event_cb);

/**
 *  描述：清理资源，退出程序前或不再使用IoCHub库调用 
 *  阻塞方式：非阻塞，立即返回
 *  返回值： 0：操作成功 
 *        203：未初始化IoCHub库，无需DeInit
 */
int IoCHub_DeInit();

/**
 *  描述： 配置IoCHub全局参数，设置参数成功后，方可调用IoCHub_Start函数，如不进行配置，则使用参数默认值
 *  阻塞方式：非阻塞，立即返回
 *  pInitCfg [IN] 配置参数内容。
 *      参数项：
 *          recvBufferSize：接收缓冲区大小，默认：1024 * 1024（字节）
 *          sendBufferSize：发送缓冲区大小，默认：1024 * 1024（字节）
 *          maxConnSize：最大会话连接数量，默认：10
 *          sendSizePerPackage：每包发送最大数据大小，默认：4 * 1024（字节）
 *          socketWndSize：发送窗口大小，即单次发送的数据帧数上限值，默认：100
 *          socketWndTimeout：ACK定时应答超时时间，默认：200（毫秒）
 *          supportCompress：是否开启数据压缩传输，收发数据时，开启后，根据待传输数据确定是否压缩传输，默认：false
 *          openDeviceLock：是否开启设备锁，开启后，NodeID与设备绑定，默认false
 *          localNetwork：本地网卡，格式如："192.168.0.93,192.168.1.100"，以英文逗号隔开
 *  返回值： 0：操作成功 
 *        203：未初始化IoCHub库
 *        318：存在未关闭的会话连接，不能进行配置
 *        701：设备已连接,不能进行参数配置
 *        703：配置参数无效或不符合要求 
 */
int IoCHub_SetCfg(IOCHUB_INIT_CFG_T * pInitCfg);

/**
 *  描述： 获取IoCHub当前参数配置
 *  阻塞方式：非阻塞，立即返回
 *  pInitCfg [OUT] 配置参数内容，参数项同IoCHub_SetCfg接口
 *  返回值： 0：操作成功
 *        203：未初始化IoCHub库
 */
int IoCHub_GetCurrentCfg(IOCHUB_INIT_CFG_T * pInitCfg);

/**
 *  描述：修改appSign
 *  阻塞方式：非阻塞，立即返回
 *  appSign [IN]软件应用标识，可为空，若不为空时，长度不能超50字符，可用于单机多应用场景
 *  返回值： 0：操作成功 
 *        203：未初始化IoCHub库
 *        701：设备已连接,不能进行参数配置
 * 		  703：配置参数无效或不符合要求 
 *        
 */
int IoCHub_ChangeAppSign(char * appSign);

/**
 * 描述： 设置访问模式模式，用于会话连接访问配置
 * 阻塞方式：非阻塞，立即返回
 * pAccessModeCfg [IN] 配置参数内容。
 *      参数项：
 *          modeType：0：公开访问，只需要NodeID即可建立会话连接
 *                    1：受限访问，需要NodeID及会话密钥建立会话连接
 *                    2：私有，不接受所有会话连接请求
 *          sessionKey：会话密钥字符串，分配不小于9个字节
 *          keySize：会话密钥字符串长度，上限值：8（字节）
 * 返回值： 0：成功， 
 *       703：配置参数无效或不符合接口要求
*/
int IoCHub_SetAccessMode(IOCHUB_ACCESS_MODE_T * pAccessModeCfg);

/**
 *  描述： 获取IoCHub当前会话模式参数配置
 *  阻塞方式：非阻塞，立即返回
 *  pAccessModeCfg [OUT] 配置参数内容，参数项同IoCHub_SetAccessMode接口
 *  返回值： 0：操作成功
 *  备注： 若未操作IoCHub_SetAccessMode进行设置，则获取到默认会话模式
 */
int IoCHub_GetAccessMode(IOCHUB_ACCESS_MODE_T * pAccessModeCfg);

/**
 * 描述： 启动IoCHub服务
 * 阻塞方式：(非)阻塞，根据syncFlag参数决定
 * svrAddr：[IN] 服务地址，格式如"58.213.74.190:38089"
 * timeout：[IN] 执行超时事件,不能低于DEFAULT_IOCHUB_START_TIMEOUT，当输入无效之后，自动设置为默认值(单位：ms)
 * syncFlag：[IN] 同步标识，false：异步（非阻塞），true：同步（阻塞）
 * 返回值： 0：成功
 *       100：注册进行中
 *       102：注册失败
 *       106：设备(客户端)认证失败
 *       110: 设备ID已占用
 *       203：未初始化IoCHub
 *       500：Socket创建失败
 *       501：Socket连接超时
 *       703：配置参数无效或不符合要求
*/
int IoCHub_Start(char *svrAddr, int timeout, bool syncFlag);

/**
 * 描述：停止IoCHub服务
 * 阻塞方式：非阻塞，立即返回
 * 返回值： 0：操作成功
 *       203：未初始化IoCHub库，无需进行Stop操作
 * 备注：关闭服务后仍然可以通过局域网扫描发现和连接设备
*/
int IoCHub_Stop();

/**
 * 描述：获取IoCHub服务启动状态
 * 阻塞方式：非阻塞，立即返回
 * 返回值： 0：不在线
 *         1：在线
*/
int IoCHub_GetStartStatus();

/**
 * 描述：设置IoCHub服务通信方式，默认高速
 * 阻塞方式：非阻塞，立即返回
 * type[IN] 通信方式，0：自适应  1：转发 
*/
void IoCHub_SetDefaultRelayTransferType(int type);

/**
 * 描述：设置IoCHub高速传输/中低速传输（高速模式：占用CPU资源较多）
 * 阻塞方式：非阻塞，立即返回
 * mode[IN] 通信方式，0：中低速传输  1：高速传输 
 *  返回值： 0：操作成功 
 *        203：未初始化IoCHub库
 *        703：配置参数无效或不符合要求 
*/
int IoCHub_SetSpeedMode(int mode);

/**
 * 描述：获取IoCHub服务通信方式
 * 阻塞方式：非阻塞，立即返回
 * 返回值： 通信方式，0：中低速传输  1：高速传输 
*/
int IoCHub_GetSpeedMode();

/**
 * 描述：打开会话
 * 阻塞方式：(非)阻塞，根据syncFlag参数决定
 * dstNodeId：[IN] 对端NodeID字符串，15~16个字符，格式如"7432FE56ABCD0332"
 * dstSessionKey：[IN] 对端会话密钥字符串，最大8个字符，格式如"12345678"
 * timeout：[IN] 执行超时事件,不能低于DEFAULT_IOCHUB_OPEN_SESSION_TIMEOUT(单位：ms)
 * syncFlag：[IN] 同步标识，false：异步（非阻塞），true：同步（阻塞）
 * 返回值：>0：sessionFd 会话句柄
 *      -203：未执行初始化调用，不能进行打开会话操作   
 *      -300：会话已存在（无需再打开）
 *      -301：自身会话数已经达到上限
 *      -302：正在打开会话过程中
 *      -303：当前设备（自身）未认证
 *      -306：打开会话失败
 *      -307：打开会话超时
 *      -310：目标NodeID为本机ID（不能连接自身）
 *      -312：对端NodeID字符串不符合规则
 *      -314：会话密钥格式不正确
 * 备注：1、返回负数时，取绝对值后为错误码；
 *      2、同步方式，返回正数即为会话打开成功，异步方式，则先分配了会话句柄，结果通过回调给出
*/
int Session_Open(const char *dstNodeId, const char *dstSessionKey, int timeout, bool syncFlag);

/**
 * 描述：关闭会话
 * 阻塞方式：非阻塞，立即返回
 * 返回值：0：操作成功 
 *      203：未初始化IoCHub，不能进行关闭会话操作
 *      400：根据会话句柄，查询会话不存在 
*/
int Session_Close(int sessionFd);

/**
 * 描述：会话读
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * readBuf：[OUT] 读取的数据，需先申请好数据空间
 * readBufLen：[IN] 待读取的数据长度
 * 返回值：>=0：实际读取到的长度
 *       -203：未初始化IoCHub，不能进行会话读操作 
 *       -400：根据会话句柄，查询会话不存在  
 * 备注：取绝对值后为错误码值，正数：实际读取的长度
*/
int Session_Read(int sessionFd, char *readBuf, int readBufLen);

/**
 * 描述：会话写操作前，获取当前缓冲区大小
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * 返回值：>=0：实际可写长度
 *       -203：未初始化IoCHub，不能进行会话读操作 
 *       -317: 会话异常，需关闭会话重新创建
 *       -400：根据会话句柄，查询会话不存在 
 * 备注：取绝对值后为错误码值，正数：实际可写长度
*/
int Session_CouldWritableLen(int sessionFd);

/**
 * 描述：会话写
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * writeBuf：[IN] 待写入的数据
 * writeBufLen：[IN] 待写入数据的长度
 * 返回值：>=0：实际写成功的长度
 *       -203：未初始化IoCHub，不能进行会话读操作 
 *       -317: 会话异常，需关闭会话重新创建
 *       -400：根据会话句柄，查询会话不存在 
 *       -401：会话发送缓冲区溢出 
 * 备注：取绝对值后为错误码值，正数：实际写成功的长度
*/
int Session_Write(int sessionFd, char *writeBuf, int writeBufLen);

/**
 * 描述：会话实时读，用于数据实时性要求高或控制命令传输
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * readBuf：[OUT] 读取的数据，需先申请好数据空间
 * readBufLen：[IN] 待读取的数据长度
 * 返回值：>=0：实际读取到的长度
 *       -203：未初始化IoCHub，不能进行会话读操作 
 *       -400：根据会话句柄，查询会话不存在  
 * 备注：取绝对值后为错误码值，正数：实际读取的长度
*/
int Session_CtrlData_Read(int sessionFd, char *readBuf, int readBufLen);

/**
 * 描述：会话写操作前，获取写操作缓冲区大小
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * 返回值：>=0：实际可写长度
 *       -203：未初始化IoCHub，不能进行会话读操作 
 *       -317: 会话异常，需关闭会话重新创建
 *       -400：根据会话句柄，查询会话不存在 
 * 备注：取绝对值后为错误码值，正数：实际可写长度
*/
int Session_CtrlData_CouldWritableLen(int sessionFd);

/**
 * 描述：会话写，用于数据实时性要求高或控制命令传输
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * writeBuf：[IN] 待写入的数据
 * writeBufLen：[IN] 待写入数据的长度
 * 返回值：>=0：实际写成功的长度
 *       -203：未初始化IoCHub，不能进行会话读操作 
 *       -317: 会话异常，需关闭会话重新创建
 *       -400：根据会话句柄，查询会话不存在 
 *       -401：会话发送缓冲区溢出 
 * 备注：取绝对值后为错误码值，正数：实际写成功的长度
*/
int Session_CtrlData_Write(int sessionFd, char *writeBuf, int writeBufLen);

/**
 * 描述：会话FIFO清理
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * 返回值：  0：操作成功 
 *       -203：未初始化IoCHub
 *       -400：根据会话句柄，查询会话不存在  
 * 备注：清除发送缓冲区
*/
int Session_ClearFifo(int sessionFd);

/**
 * 描述：获取会话传输方式
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * 返回值：0：未知
 *        1：P2P（点对点）
 *        2：RELAY（转发）
 *        3：LAN（局域网）
 *      203：未初始化IoCHub
 *      400：会话不存在
*/
int Session_GetTransferType(int sessionFd);

/**
 * 描述：获取会话传输方式
 * 阻塞方式：非阻塞，立即返回
 * sessionFd：[IN] 会话句柄
 * 返回值：0：成功
 *      203：未初始化IoCHub
 *      400：会话不存在
*/
int Session_GetNodeAddrs(int sessionFd, connected_session_addr * nodeAddrs);

/**
 * 描述：局域网内节点搜索
 * 阻塞方式：非阻塞，立即返回。
 * localNetwork：[IN] 本地网卡IP地址，如："192.168.111.93,192.168.1.100"，以英文逗号隔开
 * timeout：[IN] 局域网广播超时时间，
 * scan_cb：[IN] 局域网广播回调函数
 * 返回值：0：操作成功
 *       200：设备未注册（认证第一步）
 *       201：正在进行局域网发现
 *       204：当前设备局域网发现不可用
 * 备注：达到timeout时间后，从scan_cb回调结果
 */
int IoCHub_ScanLanNodes(char * localNetwork, int timeout, lan_scan_cb scan_cb);

/**
 * 描述：局域网内节点搜索，适用于简单及复杂局域网环境
 * 阻塞方式：非阻塞，立即返回。
 * netAddrs：[IN] 本地网卡IP地址及子网掩码，结构体
 * addrNum：[IN] 结构体数组长度
 * timeout：[IN] 局域网广播超时时间，
 * scan_cb：[IN] 局域网广播回调函数
 * 返回值：0：操作成功
 *       200：设备未注册（认证第一步）
 *       201：正在进行局域网发现
 *       204：当前设备局域网发现不可用
 * 备注：达到timeout时间后，从scan_cb回调结果
 */
int IoCHub_ScanMultiLanNodes(local_net_addr_t * netAddrs, int addrNum, int timeout, lan_scan_cb scan_cb);

/**
 *  描述：获取本机自身节点ID
 *  阻塞方式：非阻塞，立即返回。
 *  localNodeID：[OUT] 设备NodeID
 *  nodeIDSize：[OUT]  设备NodeID字符串长度
 *  返回值：0：操作成功
 *       200：设备未注册（认证第一步）
 *       203：未初始化IoCHub
 */
int IoCHub_GetLocalID(char * localNodeID, int* nodeIDSize);

/**
 *  描述：获取最后的错误
 *  阻塞方式：非阻塞，立即返回
 *  返回值：见错误码表
*/
int IoCHub_GetLastError();

/**
 *  描述：获取本机NAT类型
 *  阻塞方式：非阻塞，立即返回
 *  返回值：0：非对称类型
 *         1：全锥型
 *         2：IP受限锥型
 *         3：端口受限锥型
 *         4：具有固定IP地址（服务器）
 *        16：对称类型
 *        17：不支持UDP
 *       255：未知类型
 *      -203：未初始化IoCHub
*/
int IoCHub_GetNATType();

/**
 *  描述：获取库版本
 *  阻塞方式：非阻塞，立即返回
 *  iochubVer：[OUT] 接收版本信息的缓冲区（缓冲区至少开8个字节）
 *  verSize：[OUT] 版本号实际使用长度
 *  返回值：无
 */
void IoCHub_GetSDKVersion(char* iochubVer, int *verSize);


#ifdef __cplusplus
}
#endif

#endif  // IOCHUB_H_
